Garbage collection is automatic memory management that identifies and reclaims memory occupied by objects no longer in use. V8 implements it with a highly optimized, generational approach using multiple algorithms and parallel/concurrent techniques.
Garbage collection (GC) is the process of automatically managing memory allocation and deallocation in a running program. In languages like JavaScript, which lack explicit memory management APIs, the engine takes full responsibility for memory . The GC's job is to identify which objects are still 'alive' (reachable from root references) and which are 'dead' (unreachable), then reclaim the memory used by dead objects for future allocations . V8, Google's high-performance JavaScript engine used in Chrome and Node.js, implements a sophisticated garbage collector that has evolved significantly through the Orinoco project to minimize pauses and improve responsiveness .
Identify live/dead objects: Determine reachability starting from root set (global object, stack variables, registers) .
Recycle memory: Reclaim space occupied by dead objects and make it available for new allocations .
Compact/defragment: Optionally move objects to eliminate memory fragmentation .
V8's implementation is fundamentally based on the generational hypothesis, which observes that most objects die young—they are allocated, used briefly, and quickly become unreachable . V8 divides the heap into generations with different collection strategies optimized for object lifetimes .
The heap is split into Young Generation (new objects) and Old Generation (long-lived objects). The young generation is further divided into the 'nursery' and 'intermediate' sub-generations . Objects are first allocated in the nursery; if they survive one GC, they move to intermediate; surviving another GC promotes them to the old generation .
Algorithm: Uses Scavenger, a fast copying collector that exploits the fact few objects survive .
Semi-space design: Young generation is split into From-Space (active) and To-Space (empty). During collection, live objects are copied from From-Space to To-Space .
Cross-generation references: Maintains a list of old-to-new references via write barriers, avoiding full old generation scans .
Promotion: Objects surviving two GCs are moved (promoted) to the old generation .
Parallel execution: Modern V8 uses parallel scavenging with helper threads, each following pointers and evacuating live objects using thread-local allocation buffers .
Marking: Starts from roots, traces the entire object graph, and marks all reachable objects. Uses concurrent marking with background threads while JavaScript executes .
Write barriers: During concurrent marking, track new references created by JavaScript to maintain consistency .
Sweeping: Adds gaps from dead objects to free-lists (data structures organized by size) for future allocations .
Compaction: Selectively evacuates highly fragmented pages by copying survivors to other pages, reducing fragmentation .
The Orinoco project transformed V8's GC from a sequential, stop-the-world collector into one using parallel, incremental, and concurrent techniques .
Parallel: Multiple threads work simultaneously during pauses, dividing total pause time by thread count .
Incremental: GC work is split into small slices interleaved with JavaScript execution, spreading pauses over time .
Concurrent: Helper threads do GC work entirely in the background while the main thread runs JavaScript continuously .
V8's GC is a state-of-the-art system that balances throughput, pause times, and memory overhead through generational design, parallel scavenging, concurrent marking, and selective compaction, all working together to keep JavaScript applications fast and responsive .